#ifndef COSCMD_H
#define COSCMD_H

#include <QObject>
#include <QtEndian>

class CosCmd : public QObject
{
    Q_OBJECT
public:
    explicit CosCmd(QObject *parent = 0);

public:

    /*!
     * \brief 选择文件，SELECT。
     * \param fileId
     * \return 字符串指针。
     */
    static quint8 *getSelectFile(quint16 fileId)
    {
        //命令报文规范
        //CLA: 00, INS: A4, P1: 00/04, P2: 00, Lc: XX, Data: 空或文件标识符或DF名称, Le:00
        //P1=00:用文件标识符选择，选择当前目录下基本文件或子目录文件
        //P1=04:用目录名选择，选择MF或当前目录本身，或与当前目录平级的目录，或当前目录的下级子目录
        static quint8 cmd[16];
        cmd[0]=0x07;            // length of cmd
        cmd[1]=0x00;            // CLA
        cmd[2]=0xA4;            // INS
        cmd[3]=0x00;            // P1
        cmd[4]=0x00;            // P2
        cmd[5]=0x02;            // Lc
        cmd[6]=(fileId & 0xFF00)>>8;
        cmd[7]=(fileId & 0x00FF);
        return cmd;
    }

    /*!
     * \brief 读余额，GET BALANCE。命令执行成功后应返回4字节余额，以9000结尾。
     * \return 字符串指针。
     */
    static quint8 *getReadBalance()
    {
        //命令报文规范
        //CLA: 80, INS: 5C, P1: 00, P2: 01/02, Le: 04
        return (quint8 *)"\x05\x80\x5C\x00\x02\x04";
    }

    /*!
     * \brief 消费初始化，INITIALIZE FOR PURCHASE。
     * \param keyId 密钥标识符
     * \param nMoneyToDeduct 交易金额
     * \param termNo 终端机编号
     * \return
     */
    static quint8 *getInitForPurchase(quint8 keyId, quint32 nMoneyToDeduct, const quint8 *termNo)
    {
        //命令报文规范
        //CLA: 80, INS: 50, P1: 01, P2: 01/02, Lc: 0B, Data: 密钥标识符(1字节)+交易金额(4字节)+终端机编号(6字节), Le:0F
        //P1=01:表示此条命令用于电子存折
        //P1=02:表示此条命令用于电子钱包
        //报文执行成功之后的响应数据格式
        //电子存折或电子钱包旧余额(4字节)+电子存折或电子钱包联机交易序号(2字节)
        //+透支限额(3字节)+密钥版本号(1字节)+算法标识(1字节)+伪随机数(4字节)
        static quint8 cmd[24];
        cmd[0]=0x11;            // length of cmd
        cmd[1]=0x80;            // CLA
        cmd[2]=0x50;            // INS
        cmd[3]=0x03;            // P1 - 高速公路为00??
        cmd[4]=0x02;            // P2
        cmd[5]=0x0B;            // Lc
        cmd[6]=keyId;
        nMoneyToDeduct=qToBigEndian(nMoneyToDeduct);
        memcpy(cmd+7, &nMoneyToDeduct, 4);
        memcpy(cmd+11, termNo, 6);
        cmd[17]=0x0F;
        return cmd;
    }

    /*!
     * \brief 读记录文件, READ RECORD。
     * \param fileId 文件号, 如0x17, 0x18, 0x19。
     * \param recordNo 记录号，从1开始，否则将返回0x6a86（参数P1P2不正确）。
     * \param lenToRead 读取长度, 默认为0标识读取整条记录。
     * \return 字符串指针。
     */
    static quint8 *getReadRecord(quint8 fileId, quint8 recordNo, quint8 lenToRead=0)
    {
        //命令报文规范
        //CLA: 00/04, INS: B2, P1: 记录号, P2:记录标识 , Le: 00/XX
        //Le=00表示读取整条记录
        //Le=XX表示读取XX字节长度的记录
        //P2的4-8位为短文件标识符
        static quint8 cmd[8];
        cmd[0]=0x05;            // length of cmd
        cmd[1]=0x00;            // CLA
        cmd[2]=0xB2;            // INS
        cmd[3]=recordNo;        // P1
        cmd[4]=(fileId<<3)+0x04;// P2
        cmd[5]=lenToRead;       // Le
        return cmd;
    }

    /*!
     * \brief 读二进制文件, READ BINARY。
     * \param fileId 文件号, 如0x15, 0x16。
     * \param beginPosition 起始字节。
     * \param lenToRead 读取长度。
     * \return 字符串指针。
     */
    static quint8 *getReadBinary(quint8 fileId, quint8 beginPosition=0, quint8 lenToRead=0)
    {
        //命令报文规范
        //CLA: 00, INS: B0, P1: XX, P2:XX, Le: XX
        //若P1的高三位为100，则低五位为短文件标识，P2为读的偏移量
        //若P1的最高位不为1，则P1P2为欲读文件的偏移量，P1为偏移量的高字节，P2为偏移量的低字节，所读文件为当前文件
        static quint8 cmd[8];
        cmd[0]=0x05;            // length of cmd
        cmd[1]=0x00;            // CLA
        cmd[2]=0xB0;            // INS
        cmd[3]=fileId+0x80;     // P1
        cmd[4]=beginPosition;   // P2
        cmd[5]=lenToRead;       // Le
        return cmd;
    }

    /*!
     * \brief 验证口令，VERIFY PIN。
     * \param pinData，如"\x12\x34\x56"。
     * \param pinLen，2-6，如3。
     * \return 字符串指针。
     */
    static quint8 *getVerifyPin(const quint8 *pinData, quint8 pinLen)
    {
        //命令报文规范
        //CLA: 00, INS: 20, P1: 00, P2: 口令密钥标识符, Lc: 02-06, Data: 外部输入的口令密钥
        if (pinLen>6) pinLen=6;
        static quint8 cmd[16];
        cmd[0]=0x05+pinLen;     // length of cmd
        cmd[1]=0x00;            // CLA
        cmd[2]=0x20;            // INS
        cmd[3]=0x00;            // P1
        cmd[4]=0x00;            // P2 - 口令密钥标识符
        cmd[5]=pinLen;          // Lc
        memcpy(cmd+6, pinData, pinLen);
        return cmd;
    }

signals:

public slots:

};

#endif // COSCMD_H
